package cn.anc.aonicardv.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AbsListView;
import android.widget.Scroller;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cn.anc.aonicardv.R;

public class SlideSelectView extends View {

    private Paint mPaint;
    private double mItemWidth;
    private int mCurrentItem;
    private int mStartItem;
    private AutoScrollRecycleView mRecyclerView;
    private OnGetThumbnailListener mOnGetThumbnailListener;
    private OnScrollSelectListener mOnScrollSelectListener;
    private int mVisibleItemCount;
    private Handler handler = new Handler();
    private int mScreenWidth;
    private Scroller mScroller;
    private int mRightItemCount;
    private boolean isFromUserScroll = true;
    private int mSelectBoxLeft;
    private int mSelectBoxRight;

    public SlideSelectView(Context context, AutoScrollRecycleView recyclerView, int visibleItemCount, int rightItemCount, int currentItem) {
        this(context, null, recyclerView, visibleItemCount, rightItemCount, currentItem);
    }

    public SlideSelectView(Context context, @Nullable AttributeSet attrs, AutoScrollRecycleView recyclerView, int visibleItemCount, int rightItemCount, int currentItem) {
        super(context, attrs);
        mRecyclerView = recyclerView;
        mCurrentItem = currentItem;
        mVisibleItemCount = visibleItemCount;
        mRightItemCount = rightItemCount;
        init();
    }

    private void init() {
        mScroller = new Scroller(getContext());
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(getResources().getColor(R.color.btn_com_background));
        mPaint.setStrokeWidth(5);
        mPaint.setStyle(Paint.Style.STROKE);
        mRecyclerView.addOnScrollListener(mOnScrollListener);
        mScreenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
        mItemWidth = (mScreenWidth - mVisibleItemCount + 1) / mVisibleItemCount;
        final int[] range = calculateDisplayRange(mCurrentItem, mVisibleItemCount, mRightItemCount);
        int startItem = range[0];
        mRecyclerView.scrollToPosition(startItem);
        mRecyclerView.setScroller(mScroller);
        mStartItem = range[0];
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyGetThumbnail(getRightStartItem(range[0]), getRightEndItem(range[1]));
                notifyItemSelected(mCurrentItem);
            }
        }, 20);
    }

    private int[] calculateDisplayRange(int currentItem, int visibleItemCount, int rightItemCount) {
        int[] range = new int[2];
        if (visibleItemCount % 2 == 0) {
            throw new IllegalArgumentException("visibleItemCount is not an odd number");
        }
        int temp = visibleItemCount / 2;
        range[0] = currentItem;
        int itemCount = getRealItemCount(rightItemCount);
        if (currentItem + temp >= itemCount) {
            range[1] = itemCount - 1;
        } else {
            range[1] = range[0] + visibleItemCount - 1;
        }
        return range;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mSelectBoxLeft = (int) (getWidth() / 2 - mItemWidth / 2);
        mSelectBoxRight = (int) (getWidth() / 2 + mItemWidth / 2);
        canvas.drawRect(mSelectBoxLeft, 4, mSelectBoxRight, getHeight() - 4, mPaint);
    }

    RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() {
        private int state;

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            state = newState;
            if (state == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                int start = layoutManager.findFirstVisibleItemPosition();
                int end = layoutManager.findLastVisibleItemPosition();
                autoSlideToOptimalItem(start, end);
            } else {
                isFromUserScroll = true;
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (isFromUserScroll) {
                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                int start = layoutManager.findFirstVisibleItemPosition();
                int end = layoutManager.findLastVisibleItemPosition();
                mCurrentItem = mCurrentItem + start - mStartItem;
                mStartItem = start;
                if (state != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                    notifyGetThumbnail(getRightStartItem(start), getRightEndItem(end));
                    notifyItemSelected(mCurrentItem);
                }
            }
        }
    };

    private void notifyGetThumbnail(int start, int end) {
        if (mOnGetThumbnailListener != null) {
            mOnGetThumbnailListener.getThumbnail(start, end);
        }
    }

    private void notifyItemSelected(int position) {
        if (mOnScrollSelectListener != null) {
            mOnScrollSelectListener.onItemSelected(position);
        }
    }

    private void autoSlideToOptimalItem(int startItem, int endItem) {
        int selectPosition = 0;
        int dx = 0;
        for (int i = startItem; i <= endItem; i++) {
            if (null!=mRecyclerView.findViewHolderForAdapterPosition(i)&&null!=mRecyclerView.findViewHolderForAdapterPosition(i).itemView){
            View view = mRecyclerView.findViewHolderForAdapterPosition(i).itemView;
            int d = view.getLeft() - mSelectBoxLeft;
            if (d >= 0 && d <= mItemWidth / 2) {
                selectPosition = i;
                dx = d;
                break;
            } else if (d > mItemWidth / 2 && d < mItemWidth) {
                selectPosition = i;
                selectPosition--;
                dx = (int) -(mItemWidth - Math.abs(d));
                break;
            }
            }
        }
        mCurrentItem = getRightItemPosition(selectPosition);
        isFromUserScroll = false;
        startScroll(dx);
        final int[] range = calculateDisplayRange(mCurrentItem, mVisibleItemCount, mRightItemCount);
        int start = range[0];
        int end = range[1];
        mStartItem = start;
        notifyGetThumbnail(getRightStartItem(start), getRightEndItem(end));
        notifyItemSelected(mCurrentItem);
    }

    public void setSelectItem(int itemPosition) {
        mCurrentItem = itemPosition;
        isFromUserScroll = false;
        final int[] range = calculateDisplayRange(mCurrentItem, mVisibleItemCount, mRightItemCount);
        int startItem = range[0];
        int endItem = range[1];
        int movedItemCount = startItem - mStartItem;
        int dx = (int) ((movedItemCount * mItemWidth) + movedItemCount);
        mStartItem = startItem;
        startScroll(dx);
        notifyGetThumbnail(getRightStartItem(startItem), getRightEndItem(endItem));
    }

    private void startScroll(int dx) {
        mScroller.abortAnimation();
        mScroller.startScroll(mScroller.getCurrX(), 0, dx, 0, 1000);
        mRecyclerView.invalidate();
    }

    public int getRightItemPosition(int realItem) {
        int position = realItem - mVisibleItemCount / 2;
        return position > 0 ? position : 0;
    }

    public int getRealItemPosition(int rightItem) {
        int position = rightItem + mVisibleItemCount / 2;
        int itemCount = mRecyclerView.getAdapter().getItemCount();
        return position >= itemCount ? itemCount - 1 : position;
    }

    public int getRightStartItem(int realStartItem) {
        int start = realStartItem - mVisibleItemCount / 2;
        return start > 0 ? start : 0;
    }

    public int getRightEndItem(int realEndItem) {
        int end = realEndItem - mVisibleItemCount / 2;
        return end > (mRightItemCount - 1) ? mRightItemCount - 1 : end;
    }

    public int getRealItemCount(int rightItemCount) {
        mRightItemCount = rightItemCount;
        return mRightItemCount + mVisibleItemCount - 1;
    }

    public void setRightItemCount(int itemCount) {
        mRightItemCount = itemCount;
    }

    public boolean isUpdateItem(int position) {
        int temp = mVisibleItemCount / 2;
        return position > (temp - 1) && position < (mRightItemCount + temp);
    }

    public void setOnOnGetThumbnailListener(OnGetThumbnailListener listener) {
        mOnGetThumbnailListener = listener;
    }

    public void setOnScrollSelectListener(OnScrollSelectListener listener) {
        mOnScrollSelectListener = listener;
    }

    public interface OnGetThumbnailListener {

        void getThumbnail(int from, int to);

        void stopGetThumbnail();
    }

    public interface OnScrollSelectListener {
        void onItemSelected(int position);
    }
}
